package uk.org.landeg.euler.problems.lib;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;

public class PrimeLib {
	public static void main(String[] args) {
		testPrimeGen();
	}
	static ArrayList<Long> firstPrimes;
	static {
		firstPrimes = new ArrayList<Long>();
		firstPrimes.add(2L);
		firstPrimes.add(3L);
		firstPrimes.add(5L);
		firstPrimes.add(7L);
	}
	
	public static Set<Integer> seqPrimes (int max) {
		return seqPrimes(1, max);
	}
	
	public static Set<Integer> seqPrimes (int min, int max) {
		Set<Integer> primes = new TreeSet<Integer>();
		primes.add(2);
		primes.add(3);
		primes.add(5);
		int lastDigit;
		final int firstCandidate = firstPrimes.get(firstPrimes.size() - 1).intValue() + 1;
		boolean isPrime;
		for (int trial = firstCandidate ; trial <= max ; trial += 2) {
			if (trial % 2 == 0) {
				trial++;
			}
			lastDigit = trial % 10;
			if (lastDigit % 2 != 0 && lastDigit != 5) {
				isPrime = true;
				for (int test : primes) {
					if (test * test > trial) {
						break;
					}
					if (trial % test == 0) {
						isPrime = false;
						break;
					}
				}
				if (isPrime) {
					primes.add(trial);
				}
			}
		}
		Iterator<Integer> it = primes.iterator();
		while (it.hasNext()) {
			if (it.next() < min) {
				it.remove();
			}
		}
		return primes;
	}	
	
	public static ArrayList<Long> seqPrimes (Long max) {
		ArrayList<Long> primes = new ArrayList<Long>();
		int lastDigit; 
		primes.addAll(firstPrimes);
		boolean isPrime = true;
		for (long trial = 9 ; trial <= max ; trial+=2) {
			lastDigit = (int)(trial % 10);
			if (lastDigit != 5) {
				isPrime =true;
				for (long test : primes) {
					if (test * test > trial) {
						break;
					}
					if (trial % test == 0) {
						isPrime = false;
						break;
					}
				}
				if (isPrime) {
					primes.add(trial);
				}
			}
		}
		return primes;
	}
	
	public static ArrayList<Long> seqNPrimes (Long count) {
		ArrayList<Long> primes = new ArrayList<Long>();
		int lastDigit; 
		primes.addAll(firstPrimes);
		boolean isPrime = true;
		final int firstCandidate = firstPrimes.get(firstPrimes.size() - 1).intValue() + 1;
		long trial = firstCandidate;
		if (trial % 2 == 0) {
			trial++;
		}
		do {
			lastDigit = (int)(trial % 10);
			if (lastDigit != 5) {
				isPrime =true;
				for (long test : primes) {
					if (test * test > trial) {
						break;
					}
					if (trial % test == 0) {
						isPrime = false;
						break;
					}
				}
				if (isPrime) {
					primes.add(trial);
				}
			}
			trial += 2;
		} while (primes.size() < count);
		return primes;
	}
	
	
	static void testPrimeGen () {
		System.out.println(seqPrimes(10L));
		System.out.println(seqPrimes(17L));

		System.out.println(seqPrimes(1000L));
	}
}
